<!DOCTYPE html>
<html>

<head>
  <title>Using Reactive Routes</title>
  <script id="adobe_dtm" src="https://www.redhat.com/dtm.js" type="text/javascript"></script>
  <script src="/assets/javascript/highlight.pack.js" type="text/javascript"></script>
  <META HTTP-EQUIV='Content-Security-Policy' CONTENT="default-src 'none'; script-src 'self' 'unsafe-eval' 'sha256-ANpuoVzuSex6VhqpYgsG25OHWVA1I+F6aGU04LoI+5s=' 'sha256-ipy9P/3rZZW06mTLAR0EnXvxSNcnfSDPLDuh3kzbB1w=' js.bizographics.com https://www.redhat.com assets.adobedtm.com jsonip.com https://ajax.googleapis.com https://www.googletagmanager.com https://www.google-analytics.com https://use.fontawesome.com; style-src 'self' https://fonts.googleapis.com https://use.fontawesome.com; img-src 'self' *; media-src 'self' ; frame-src https://www.googletagmanager.com https://www.youtube.com; frame-ancestors 'none'; base-uri 'none'; object-src 'none'; form-action 'none'; font-src 'self' https://use.fontawesome.com https://fonts.gstatic.com;">
  <META HTTP-EQUIV='X-Frame-Options' CONTENT="DENY">
  <META HTTP-EQUIV='X-XSS-Protection' CONTENT="1; mode=block">
  <META HTTP-EQUIV='X-Content-Type-Options' CONTENT="nosniff">
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <meta name="description" content="Quarkus: Supersonic Subatomic Java">
  <meta name="twitter:card" content="summary_large_image">
  <meta name="twitter:site" content="@QuarkusIO"> 
  <meta name="twitter:creator" content="@QuarkusIO">
  <meta property="og:url" content="https://quarkus.io/guides/reactive-routes" />
  <meta property="og:title" content="Using Reactive Routes" />
  <meta property="og:description" content="Quarkus: Supersonic Subatomic Java" />
  <meta property="og:image" content="/assets/images/quarkus_card.png" />
  <link rel="canonical" href="https://quarkus.io/guides/reactive-routes">
  <link rel="shortcut icon" type="image/png" href="/favicon.ico" >
  <link rel="stylesheet" href="https://quarkus.io/guides/stylesheet/config.css" />
  <link rel="stylesheet" href="/assets/css/main.css" />
  <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.1.0/css/all.css" integrity="sha384-lKuwvrZot6UHsBSfcMvOkWwlCMgc0TaWr+30HWe3a4ltaBwTZhyTEggF5tJv8tbt" crossorigin="anonymous">
  <link rel="alternate" type="application/rss+xml"  href="https://quarkus.io/feed.xml" title="Quarkus">
  <script src="https://quarkus.io/assets/javascript/goan.js" type="text/javascript"></script>
  <script src="https://quarkus.io/assets/javascript/hl.js" type="text/javascript"></script>
</head>

<body class="guides">
  <!-- Google Tag Manager (noscript) -->
  <noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-NJWS5L"
  height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
  <!-- End Google Tag Manager (noscript) -->

  <div class="nav-wrapper">
  <div class="grid-wrapper">
    <div class="width-12-12">
      <input type="checkbox" id="checkbox" />
      <nav id="main-nav" class="main-nav">
  <div class="container">
    <div class="logo-wrapper">
      
        <a href="/"><img src="/assets/images/quarkus_logo_horizontal_rgb_600px_reverse.png" class="project-logo" title="Quarkus"></a>
      
    </div>
    <label class="nav-toggle" for="checkbox">
      <i class="fa fa-bars"></i>
    </label>
    <div id="menu" class="menu">
      <span>
        <a href="/get-started/" class="">Get Started</a>
      </span>
      <span>
        <a href="/guides/" class="active">Guides</a>
      </span>
      <span>
        <a href="/community/" class="">Community</a>
      </span>
      <span>
        <a href="/support/" class="">Support</a>
      </span>
      <span>
        <a href="/blog/" class="">Blog</a>
      </span>
      <span>
        <a href="https://code.quarkus.io" class="button-cta secondary white">Start Coding</a>
      </span>
    </div>
  </div>
      </nav>
    </div>
  </div>
</div>

  <div class="content">
    <div class="guide">
  <div class="width-12-12">
    <h1 class="text-caps">Using Reactive Routes</h1>
    <div class="hide-mobile toc"><ul class="sectlevel1">
<li><a href="#quarkus-http">Quarkus HTTP</a></li>
<li><a href="#declaring-reactive-routes">Declaring reactive routes</a>
<ul class="sectlevel2">
<li><a href="#handling-conflicting-routes">Handling conflicting routes</a></li>
<li><a href="#routebase"><code>@RouteBase</code></a></li>
</ul>
</li>
<li><a href="#reactive-route-methods">Reactive Route Methods</a>
<ul class="sectlevel2">
<li><a href="#returning-unis">Returning Unis</a></li>
<li><a href="#returning-results">Returning results</a></li>
<li><a href="#returning-multis">Returning Multis</a></li>
<li><a href="#streaming-json-array-items">Streaming JSON Array items</a></li>
<li><a href="#event-stream-and-server-sent-event-support">Event Stream and Server-Sent Event support</a></li>
</ul>
</li>
<li><a href="#using-the-vert-x-web-router">Using the Vert.x Web Router</a></li>
<li><a href="#intercepting-http-requests">Intercepting HTTP requests</a></li>
<li><a href="#adding-openapi-and-swagger-ui">Adding OpenAPI and Swagger UI</a>
<ul class="sectlevel2">
<li><a href="#adding-microprofile-openapi-annotations">Adding MicroProfile OpenAPI Annotations</a></li>
<li><a href="#using-swagger-ui">Using Swagger UI</a></li>
</ul>
</li>
<li><a href="#conclusion">Conclusion</a></li>
</ul></div>
    <div>
      <div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p>Reactive routes propose an alternative approach to implement HTTP endpoints where you declare and chain <em>routes</em>.
This approach became very popular in the JavaScript world, with frameworks like Express.Js or Hapi.
Quarkus also offers the possibility to use reactive routes.
You can implement REST API with routes only or combine them with JAX-RS resources and servlets.</p>
</div>
<div class="paragraph">
<p>The code presented in this guide is available in this <a href="https://github.com/quarkusio/quarkus-quickstarts">Github repository</a> under the <a href="https://github.com/quarkusio/quarkus-quickstarts/tree/master/reactive-routes-quickstart"><code>reactive-routes-quickstart</code> directory</a></p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="quarkus-http"><a class="anchor" href="#quarkus-http"></a>Quarkus HTTP</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Before going further, let&#8217;s have a look at the HTTP layer of Quarkus.
Quarkus HTTP support is based on a non-blocking and reactive engine (Eclipse Vert.x and Netty).
All the HTTP requests your application receive are handled by <em>event loops</em> (IO Thread) and then are routed towards the code that manages the request.
Depending on the destination, it can invoke the code managing the request on a worker thread (Servlet, Jax-RS) or use the IO Thread (reactive route).
Note that because of this, a reactive route must be non-blocking or explicitly declare its blocking nature (which would result by being called on a worker thread).</p>
</div>
<div class="paragraph">
<p><span class="image"><img src="/guides/images/http-architecture.png" alt="Quarkus HTTP Architecture"></span></p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="declaring-reactive-routes"><a class="anchor" href="#declaring-reactive-routes"></a>Declaring reactive routes</h2>
<div class="sectionbody">
<div class="paragraph">
<p>The first way to use reactive routes is to use the <code>@Route</code> annotation.
To have access to this annotation, you need to add the <code>quarkus-vertx-web</code> extension:</p>
</div>
<div class="paragraph">
<p>In your <code>pom.xml</code> file, add:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="xml" class="language-xml hljs">&lt;dependency&gt;
    &lt;groupId&gt;io.quarkus&lt;/groupId&gt;
    &lt;artifactId&gt;quarkus-vertx-web&lt;/artifactId&gt;
&lt;/dependency&gt;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Then in a <em>bean</em>, you can use the <code>@Route</code> annotation as follows:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">package org.acme.reactive.routes;

import io.quarkus.vertx.web.Route;
import io.quarkus.vertx.web.RoutingExchange;
import io.vertx.core.http.HttpMethod;
import io.vertx.ext.web.RoutingContext;

import javax.enterprise.context.ApplicationScoped;

@ApplicationScoped <i class="conum" data-value="1"></i><b>(1)</b>
public class MyDeclarativeRoutes {

    // neither path nor regex is set - match a path derived from the method name
    @Route(methods = HttpMethod.GET) <i class="conum" data-value="2"></i><b>(2)</b>
    void hello(RoutingContext rc) { <i class="conum" data-value="3"></i><b>(3)</b>
        rc.response().end("hello");
    }

    @Route(path = "/world")
    String helloWorld() { <i class="conum" data-value="4"></i><b>(4)</b>
        return "Hello world!";
    }

    @Route(path = "/greetings", methods = HttpMethod.GET)
    void greetings(RoutingExchange ex) { <i class="conum" data-value="5"></i><b>(5)</b>
        ex.ok("hello " + ex.getParam("name").orElse("world"));
    }
}</code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>If there is a reactive route found on a class with no scope annotation then <code>@javax.inject.Singleton</code> is added automatically.</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>The <code>@Route</code> annotation indicates that the method is a reactive route. Again, by default, the code contained in the method must not block.</td>
</tr>
<tr>
<td><i class="conum" data-value="3"></i><b>3</b></td>
<td>The method gets a <a href="https://vertx.io/docs/apidocs/io/vertx/ext/web/RoutingContext.html"><code>RoutingContext</code></a> as a parameter. From the <code>RoutingContext</code> you can retrieve the HTTP request (using <code>request()</code>) and write the response using <code>response().end(&#8230;&#8203;)</code>.</td>
</tr>
<tr>
<td><i class="conum" data-value="4"></i><b>4</b></td>
<td>If the annotated method does not return <code>void</code> the arguments are optional.</td>
</tr>
<tr>
<td><i class="conum" data-value="5"></i><b>5</b></td>
<td><code>RoutingExchange</code> is a convenient wrapper of <code>RoutingContext</code> which provides some useful methods.</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>More details about using the <code>RoutingContext</code> is available in the <a href="https://vertx.io/docs/vertx-web/java/">Vert.x Web documentation</a>.</p>
</div>
<div class="paragraph">
<p>The <code>@Route</code> annotation allows you to configure:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>The <code>path</code> - for routing by path, using the <a href="https://vertx.io/docs/vertx-web/java/#_capturing_path_parameters">Vert.x Web format</a></p>
</li>
<li>
<p>The <code>regex</code> - for routing with regular expressions, see <a href="https://vertx.io/docs/vertx-web/java/#_routing_with_regular_expressions">for more details</a></p>
</li>
<li>
<p>The <code>methods</code> - the HTTP verb triggering the route such as <code>GET</code>, <code>POST</code>&#8230;&#8203;</p>
</li>
<li>
<p>The <code>type</code> - it can be <em>normal</em> (non-blocking), <em>blocking</em> (method dispatched on a worker thread), or <em>failure</em> to indicate that this route is called on failures</p>
</li>
<li>
<p>The <code>order</code> - the order of the route when several routes are involved in handling the incoming request.
Must be positive for regular user routes.</p>
</li>
<li>
<p>The produced and consumed mime types using <code>produces</code>, and <code>consumes</code></p>
</li>
</ul>
</div>
<div class="paragraph">
<p>For instance, you can declare a blocking route as follows:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">@Route(methods = HttpMethod.POST, path = "/post", type = Route.HandlerType.BLOCKING)
public void blocking(RoutingContext rc) {
    // ...
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>The <code>@Route</code> annotation is repeatable and so you can declare several routes for a single method:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">@Route(path = "/first") <i class="conum" data-value="1"></i><b>(1)</b>
@Route(path = "/second")
public void route(RoutingContext rc) {
    // ...
}</code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>Each route can use different paths, methods&#8230;&#8203;</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>If no content-type header is set then we will try to use the most acceptable content type as defined by <code>io.vertx.ext.web.RoutingContext.getAcceptableContentType()</code>.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">@Route(path = "/person", produces = "text/html") <i class="conum" data-value="1"></i><b>(1)</b>
String person() {
    // ...
}</code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>If the <code>accept</code> header matches <code>text/html</code> we set the content type automatically.</td>
</tr>
</table>
</div>
<div class="sect2">
<h3 id="handling-conflicting-routes"><a class="anchor" href="#handling-conflicting-routes"></a>Handling conflicting routes</h3>
<div class="paragraph">
<p>You may end up with multiple routes matching a given path.
In the following example, both route matches <code>/accounts/me</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">@Route(path = "/accounts/:id", methods = HttpMethod.GET)
void getAccount(RoutingContext ctx) {
  ...
}

@Route(path = "/accounts/me", methods = HttpMethod.GET)
void getCurrentUserAccount(RoutingContext ctx) {
  ...
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>As a consequence, the result is not the expected one as the first route is called with the path parameter <code>id</code> set to <code>me</code>.
To avoid the conflict, use the <code>order</code> attribute:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">@Route(path = "/accounts/:id", methods = HttpMethod.GET, order = 2)
void getAccount(RoutingContext ctx) {
  ...
}

@Route(path = "/accounts/me", methods = HttpMethod.GET, order = 1)
void getCurrentUserAccount(RoutingContext ctx) {
  ...
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>By giving a lower order to the second route, it gets evaluated first.
If the request path matches, it is invoked, otherwise the other routes are evaluated.</p>
</div>
</div>
<div class="sect2">
<h3 id="routebase"><a class="anchor" href="#routebase"></a><code>@RouteBase</code></h3>
<div class="paragraph">
<p>This annotation can be used to configure some defaults for reactive routes declared on a class.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">@RouteBase(path = "simple", produces = "text/plain") <i class="conum" data-value="1"></i><b>(1)</b> <i class="conum" data-value="2"></i><b>(2)</b>
public class SimpleRoutes {

    @Route(path = "ping") // the final path is /simple/ping
    void ping(RoutingContext rc) {
        rc.response().end("pong");
    }
}</code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>The <code>path</code> value is used as a prefix for any route method declared on the class where <code>Route#path()</code> is used.</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>The value of <code>produces()</code> is used for content-based routing for all routes where <code>Route#produces()</code> is empty.</td>
</tr>
</table>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="reactive-route-methods"><a class="anchor" href="#reactive-route-methods"></a>Reactive Route Methods</h2>
<div class="sectionbody">
<div class="paragraph">
<p>A route method must be a non-private non-static method of a CDI bean.
If the annotated method returns <code>void</code> then it has to accept at least one argument - see the supported types below.
If the annotated method does not return <code>void</code> then the arguments are optional.</p>
</div>
<div class="paragraph">
<p>A route method can accept arguments of the following types:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><code>io.vertx.ext.web.RoutingContext</code></p>
</li>
<li>
<p><code>io.vertx.reactivex.ext.web.RoutingContext</code></p>
</li>
<li>
<p><code>io.quarkus.vertx.web.RoutingExchange</code></p>
</li>
<li>
<p><code>io.vertx.core.http.HttpServerRequest</code></p>
</li>
<li>
<p><code>io.vertx.core.http.HttpServerResponse</code></p>
</li>
<li>
<p><code>io.vertx.reactivex.core.http.HttpServerRequest</code></p>
</li>
<li>
<p><code>io.vertx.reactivex.core.http.HttpServerResponse</code></p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Furthermore, it is possible to inject the <code>HttpServerRequest</code> parameters into a method parameter annotated with <code>@io.quarkus.vertx.web.Param</code>:</p>
</div>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 50%;">
<col style="width: 50%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Parameter Type</th>
<th class="tableblock halign-left valign-top">Obtained via</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>java.lang.String</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>routingContext.request().getParam()</code></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>java.util.Optional&lt;String&gt;</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>routingContext.request().getParam()</code></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>java.util.List&lt;String&gt;</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>routingContext.request().params().getAll()</code></p></td>
</tr>
</tbody>
</table>
<div class="listingblock">
<div class="title">Request Parameter Example</div>
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">@Route
String hello(@Param Optional&lt;String&gt; name) {
   return "Hello " + name.orElse("world");
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>The <code>HttpServerRequest</code> headers can be injected into a method parameter annotated with <code>@io.quarkus.vertx.web.Header</code>:</p>
</div>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 50%;">
<col style="width: 50%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Parameter Type</th>
<th class="tableblock halign-left valign-top">Obtained via</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>java.lang.String</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>routingContext.request().getHeader()</code></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>java.util.Optional&lt;String&gt;</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>routingContext.request().getHeader()</code></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>java.util.List&lt;String&gt;</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>routingContext.request().headers().getAll()</code></p></td>
</tr>
</tbody>
</table>
<div class="listingblock">
<div class="title">Request Header Example</div>
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">@Route
String helloFromHeader(@Header("My-Header") String header) {
   return header;
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>The request body can be injected into a method parameter annotated with <code>@io.quarkus.vertx.web.Body</code>.</p>
</div>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 50%;">
<col style="width: 50%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Parameter Type</th>
<th class="tableblock halign-left valign-top">Obtained via</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>java.lang.String</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>routingContext.getBodyAsString()</code></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>io.vertx.core.buffer.Buffer</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>routingContext.getBody()</code></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>io.vertx.core.json.JsonObject</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>routingContext.getBodyAsJson()</code></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>io.vertx.core.json.JsonArray</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>routingContext.getBodyAsJsonArray()</code></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">any other type</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>routingContext.getBodyAsJson().mapTo(MyPojo.class)</code></p></td>
</tr>
</tbody>
</table>
<div class="listingblock">
<div class="title">Request Body Example</div>
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">@Route(produces = "application/json")
Person createPerson(@Body Person person, @Param("id") Optional&lt;String&gt; primaryKey) {
  person.setId(primaryKey.map(Integer::valueOf).orElse(42));
  return person;
}</code></pre>
</div>
</div>
<div class="sect2">
<h3 id="returning-unis"><a class="anchor" href="#returning-unis"></a>Returning Unis</h3>
<div class="paragraph">
<p>In a reactive route, you can return a <code>Uni</code> directly:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">@Route(path = "/hello")
Uni&lt;String&gt; hello(RoutingContext context) {
    return Uni.createFrom().item("Hello world!");
}

@Route(path = "/person")
Uni&lt;Person&gt; getPerson(RoutingContext context) {
    return Uni.createFrom().item(() -&gt; new Person("neo", 12345));
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Returning <code>Unis</code> is convenient when using a reactive client:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">@Route(path = "/mail")
Uni&lt;Void&gt; sendEmail(RoutingContext context) {
    return mailer.send(...);
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>The item produced by the returned <code>Uni</code> can be:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>a string - written into the HTTP response directly</p>
</li>
<li>
<p>a buffer - written into the HTTP response directly</p>
</li>
<li>
<p>an object - written into the HTTP response after having been encoded into JSON.
The <code>content-type</code> header is set to <code>application/json</code> if not already set.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>If the returned <code>Uni</code> produces a failure (or is <code>null</code>), an HTTP 500 response is written.</p>
</div>
<div class="paragraph">
<p>Returning a <code>Uni&lt;Void&gt;</code> produces a 204 response (no content).</p>
</div>
</div>
<div class="sect2">
<h3 id="returning-results"><a class="anchor" href="#returning-results"></a>Returning results</h3>
<div class="paragraph">
<p>You can also return a result directly:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">@Route(path = "/hello")
String helloSync(RoutingContext context) {
    return "Hello world";
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Be aware, the processing must be <strong>non-blocking</strong> as reactive routes are invoked on the IO Thread.
Otherwise, use the <code>blocking</code> attribute of the <code>@Route</code> annotation.</p>
</div>
<div class="paragraph">
<p>The method can return:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>a string - written into the HTTP response directly</p>
</li>
<li>
<p>a buffer - written into the HTTP response directly</p>
</li>
<li>
<p>an object - written into the HTTP response after having been encoded into JSON.
The <code>content-type</code> header is set to <code>application/json</code> if not already set.</p>
</li>
</ul>
</div>
</div>
<div class="sect2">
<h3 id="returning-multis"><a class="anchor" href="#returning-multis"></a>Returning Multis</h3>
<div class="paragraph">
<p>A reactive route can return a <code>Multi</code>.
The items are written one by one, in the response.
The response <code>Transfer-Encoding</code> header is set to <code>chunked</code>.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">@Route(path = "/hello")
Multi&lt;String&gt; hellos(RoutingContext context) {
    return Multi.createFrom().items("hello", "world", "!");  <i class="conum" data-value="1"></i><b>(1)</b>
}</code></pre>
</div>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Produces <code>helloworld!</code></p>
</li>
</ol>
</div>
<div class="paragraph">
<p>The method can return:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>a <code>Multi&lt;String&gt;</code> - the items are written one by one (one per <em>chunk</em>) in the response.</p>
</li>
<li>
<p>a <code>Multi&lt;Buffer&gt;</code> - the buffers are written one by one (one per <em>chunk</em>) without any processing.</p>
</li>
<li>
<p>a <code>Multi&lt;Object&gt;</code> - the items are encoded to JSON written one by one in the response.</p>
</li>
</ul>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">@Route(path = "/people")
Multi&lt;Person&gt; people(RoutingContext context) {
    return Multi.createFrom().items(
            new Person("superman", 1),
            new Person("batman", 2),
            new Person("spiderman", 3));
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>The previous snippet produces:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="json" class="language-json hljs">{"name":"superman", "id": 1} // chunk 1
{"name":"batman", "id": 2} // chunk 2
{"name":"spiderman", "id": 3} // chunk 3</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="streaming-json-array-items"><a class="anchor" href="#streaming-json-array-items"></a>Streaming JSON Array items</h3>
<div class="paragraph">
<p>You can return a <code>Multi</code> to produce a JSON Array, where every item is an item from this array.
The response is written item by item to the client.
The <code>content-type</code> is set to <code>application/json</code> if not set already.</p>
</div>
<div class="paragraph">
<p>To use this feature, you need to wrap the returned <code>Multi</code> using <code>io.quarkus.vertx.web.ReactiveRoutes.asJsonArray</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">@Route(path = "/people")
Multi&lt;Person&gt; people(RoutingContext context) {
    return ReactiveRoutes.asJsonArray(Multi.createFrom().items(
            new Person("superman", 1),
            new Person("batman", 2),
            new Person("spiderman", 3)));
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>The previous snippet produces:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="json" class="language-json hljs">[
  {"name":"superman", "id": 1} // chunk 1
  ,{"name":"batman", "id": 2} // chunk 2
  ,{"name":"spiderman", "id": 3} // chunk 3
]</code></pre>
</div>
</div>
<div class="paragraph">
<p>Only <code>Multi&lt;String&gt;</code>, <code>Multi&lt;Object&gt;</code> and <code>Multi&lt;Void&gt;</code> can be written into the JSON Array.
Using a <code>Multi&lt;Void&gt;</code> produces an empty array.
You cannot use <code>Multi&lt;Buffer&gt;</code>.
If you need to use <code>Buffer</code>, transform the content into a JSON or String representation first.</p>
</div>
</div>
<div class="sect2">
<h3 id="event-stream-and-server-sent-event-support"><a class="anchor" href="#event-stream-and-server-sent-event-support"></a>Event Stream and Server-Sent Event support</h3>
<div class="paragraph">
<p>You can return a <code>Multi</code> to produce an event source (stream of server sent events).
To enable this feature, you need to wrap the returned <code>Multi</code> using <code>io.quarkus.vertx.web.ReactiveRoutes.asEventStream</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">@Route(path = "/people")
Multi&lt;Person&gt; people(RoutingContext context) {
    return ReactiveRoutes.asEventStream(Multi.createFrom().items(
            new Person("superman", 1),
            new Person("batman", 2),
            new Person("spiderman", 3)));
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>This method would produce:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="text" class="language-text hljs">data: {"name":"superman", "id": 1}
id: 0

data: {"name":"batman", "id": 2}
id: 1

data: {"name":"spiderman", "id": 3}
id: 2</code></pre>
</div>
</div>
<div class="paragraph">
<p>You can also implement the <code>io.quarkus.vertx.web.ReactiveRoutes.ServerSentEvent</code> interface to customize the <code>event</code> and <code>id</code> section of the server sent event:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">class PersonEvent implements ReactiveRoutes.ServerSentEvent&lt;Person&gt; {
    public String name;
    public int id;

    public PersonEvent(String name, int id) {
        this.name = name;
        this.id = id;
    }

    @Override
    public Person data() {
        return new Person(name, id); // Will be JSON encoded
    }

    @Override
    public long id() {
        return id;
    }

    @Override
    public String event() {
        return "person";
    }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Using a <code>Multi&lt;PersonEvent&gt;</code> (wrapped using <code>io.quarkus.vertx.web.ReactiveRoutes.asEventStream</code>) would produce:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="text" class="language-text hljs">event: person
data: {"name":"superman", "id": 1}
id: 1

event: person
data: {"name":"batman", "id": 2}
id: 2

event: person
data: {"name":"spiderman", "id": 3}
id: 3</code></pre>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="using-the-vert-x-web-router"><a class="anchor" href="#using-the-vert-x-web-router"></a>Using the Vert.x Web Router</h2>
<div class="sectionbody">
<div class="paragraph">
<p>You can also register your route directly on the <em>HTTP routing layer</em> by registering routes directly on the <code>Router</code> object.
To retrieve the <code>Router</code> instance at startup:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">public void init(@Observes Router router) {
    router.get("/my-route").handler(rc -&gt; rc.response().end("Hello from my route"));
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Check the <a href="https://vertx.io/docs/vertx-web/java/#_basic_vert_x_web_concepts">Vert.x Web documentation</a> to know more about the route registration, options, and available handlers.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
<div class="paragraph">
<p><code>Router</code> access is provided by the <code>quarkus-vertx-http</code> extension.
If you use <code>quarkus-resteasy</code> or <code>quarkus-vertx-web</code>, the extension will be added automatically.</p>
</div>
</td>
</tr>
</table>
</div>
</div>
</div>
<div class="sect1">
<h2 id="intercepting-http-requests"><a class="anchor" href="#intercepting-http-requests"></a>Intercepting HTTP requests</h2>
<div class="sectionbody">
<div class="paragraph">
<p>You can also register filters that would intercept incoming HTTP requests.
Note that these filters are also applied for servlets, JAX-RS resources, and reactive routes.</p>
</div>
<div class="paragraph">
<p>For example, the following code snippet registers a filter adding an HTTP header:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">package org.acme.reactive.routes;

import io.vertx.ext.web.RoutingContext;

public class MyFilters {

    @RouteFilter(100) <i class="conum" data-value="1"></i><b>(1)</b>
    void myFilter(RoutingContext rc) {
       rc.response().putHeader("X-Header", "intercepting the request");
       rc.next(); <i class="conum" data-value="2"></i><b>(2)</b>
    }
}</code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>The <code>RouteFilter#value()</code> defines the priority used to sort the filters - filters with higher priority are called first.</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>The filter is likely required to call the <code>next()</code> method to continue the chain.</td>
</tr>
</table>
</div>
</div>
</div>
<div class="sect1">
<h2 id="adding-openapi-and-swagger-ui"><a class="anchor" href="#adding-openapi-and-swagger-ui"></a>Adding OpenAPI and Swagger UI</h2>
<div class="sectionbody">
<div class="paragraph">
<p>You can add support for <a href="https://www.openapis.org/">OpenAPI</a> and <a href="https://swagger.io/tools/swagger-ui/">Swagger UI</a> by using the <code>quarkus-smallrye-openapi</code> extension.</p>
</div>
<div class="paragraph">
<p>Add the extension by running this command:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="bash" class="language-bash hljs">./mvnw quarkus:add-extension -Dextensions="io.quarkus:quarkus-smallrye-openapi"</code></pre>
</div>
</div>
<div class="paragraph">
<p>This will add the following to your <code>pom.xml</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="xml" class="language-xml hljs">&lt;dependency&gt;
    &lt;groupId&gt;io.quarkus&lt;/groupId&gt;
    &lt;artifactId&gt;quarkus-smallrye-openapi&lt;/artifactId&gt;
&lt;/dependency&gt;</code></pre>
</div>
</div>
<div class="paragraph">
<p>This is enough to generate a basic OpenAPI schema document from your Vert.x Routes:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="bash" class="language-bash hljs">curl http://localhost:8080/openapi</code></pre>
</div>
</div>
<div class="paragraph">
<p>You will see the generated OpenAPI schema document:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="yaml" class="language-yaml hljs">---
openapi: 3.0.3
info:
  title: Generated API
  version: "1.0"
paths:
  /greetings:
    get:
      responses:
        "204":
          description: No Content
  /hello:
    get:
      responses:
        "204":
          description: No Content
  /world:
    get:
      responses:
        "200":
          description: OK
          content:
            '*/*':
              schema:
                type: string</code></pre>
</div>
</div>
<div class="paragraph">
<p>Also see <a href="openapi-swaggerui">the OpenAPI Guide</a>.</p>
</div>
<div class="sect2">
<h3 id="adding-microprofile-openapi-annotations"><a class="anchor" href="#adding-microprofile-openapi-annotations"></a>Adding MicroProfile OpenAPI Annotations</h3>
<div class="paragraph">
<p>You can use <a href="https://github.com/eclipse/microprofile-open-api">MicroProfile OpenAPI</a> to better document your schema,
example, adding header info, or specifying the return type on <code>void</code> methods might be usefull :</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">@OpenAPIDefinition(<i class="conum" data-value="1"></i><b>(1)</b>
    info = @Info(
        title="Greeting API",
        version = "1.0.1",
        contact = @Contact(
            name = "Greeting API Support",
            url = "http://exampleurl.com/contact",
            email = "techsupport@example.com"),
        license = @License(
            name = "Apache 2.0",
            url = "http://www.apache.org/licenses/LICENSE-2.0.html"))
)
@ApplicationScoped
public class MyDeclarativeRoutes {

    // neither path nor regex is set - match a path derived from the method name
    @Route(methods = HttpMethod.GET)
    @APIResponse(responseCode="200",
            description="Say hello",
            content=@Content(mediaType="application/json", schema=@Schema(type=SchemaType.STRING)))<i class="conum" data-value="2"></i><b>(2)</b>
    void hello(RoutingContext rc) {
        rc.response().end("hello");
    }

    @Route(path = "/world")
    String helloWorld() {
        return "Hello world!";
    }

    @Route(path = "/greetings", methods = HttpMethod.GET)
    @APIResponse(responseCode="200",
            description="Greeting",
            content=@Content(mediaType="application/json", schema=@Schema(type=SchemaType.STRING)))
    void greetings(RoutingExchange ex) {
        ex.ok("hello " + ex.getParam("name").orElse("world"));
    }
}</code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>Header information about your API.</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>Defining the response</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>This will generate this OpenAPI schema:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="yaml" class="language-yaml hljs">---
openapi: 3.0.3
info:
  title: Greeting API
  contact:
    name: Greeting API Support
    url: http://exampleurl.com/contact
    email: techsupport@example.com
  license:
    name: Apache 2.0
    url: http://www.apache.org/licenses/LICENSE-2.0.html
  version: 1.0.1
paths:
  /greetings:
    get:
      responses:
        "200":
          description: Greeting
          content:
            application/json:
              schema:
                type: string
  /hello:
    get:
      responses:
        "200":
          description: Say hello
          content:
            application/json:
              schema:
                type: string
  /world:
    get:
      responses:
        "200":
          description: OK
          content:
            '*/*':
              schema:
                type: string</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="using-swagger-ui"><a class="anchor" href="#using-swagger-ui"></a>Using Swagger UI</h3>
<div class="paragraph">
<p>Swagger UI is included by default when running in <code>dev</code> or <code>test</code> mode, and can optionally added to <code>prod</code> mode.
See <a href="openapi-swaggerui#use-swagger-ui-for-development">the Swagger UI</a> Guide for more details.</p>
</div>
<div class="paragraph">
<p>Navigate to <a href="http://localhost:8080/swagger-ui/">localhost:8080/swagger-ui/</a> and you will see the Swagger UI screen:</p>
</div>
<div class="paragraph">
<p><span class="image"><img src="/guides/images/reactive-routes-guide-screenshot01.png" alt="Swagger UI"></span></p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="conclusion"><a class="anchor" href="#conclusion"></a>Conclusion</h2>
<div class="sectionbody">
<div class="paragraph">
<p>This guide has introduced how you can use reactive routes to define an HTTP endpoint.
It also describes the structure of the Quarkus HTTP layer and how to write filters.</p>
</div>
</div>
</div>
    </div>
  </div>
</div>

  </div>

  <div class="content project-footer">
  <div class="footer-section">
    <div class="logo-wrapper">
      <a href="/"><img src="/assets/images/quarkus_logo_horizontal_rgb_reverse.svg" class="project-logo" title="Quarkus"></a>
    </div>
  </div>
  <div class="grid-wrapper">
    <p class="grid__item width-3-12">Quarkus is open. All dependencies of this project are available under the <a href='https://www.apache.org/licenses/LICENSE-2.0' target='_blank'>Apache Software License 2.0</a> or compatible license.<br /><br />This website was built with <a href='https://jekyllrb.com/' target='_blank'>Jekyll</a>, is hosted on <a href='https://pages.github.com/' target='_blank'>Github Pages</a> and is completely open source. If you want to make it better, <a href='https://github.com/quarkusio/quarkusio.github.io' target='_blank'>fork the website</a> and show us what you’ve got.</p>

    
      <div class="width-1-12 project-links">
        <span>Navigation</span>
        <ul class="footer-links width-1-12">
          
            <li><a href="/">Home</a></li>
          
            <li><a href="/guides">Guides</a></li>
          
            <li><a href="/community/#contributing">Contribute</a></li>
          
            <li><a href="/faq">FAQ</a></li>
          
            <li><a href="/get-started">Get Started</a></li>
          
        </ul>
      </div>
    
      <div class="width-1-12 project-links">
        <span>Contribute</span>
        <ul class="footer-links width-1-12">
          
            <li><a href="https://twitter.com/quarkusio">Follow us</a></li>
          
            <li><a href="https://github.com/quarkusio">GitHub</a></li>
          
            <li><a href="/security">Security&nbsp;policy</a></li>
          
        </ul>
      </div>
    
      <div class="width-1-12 project-links">
        <span>Get Help</span>
        <ul class="footer-links width-1-12">
          
            <li><a href="https://groups.google.com/forum/#!forum/quarkus-dev">Forums</a></li>
          
            <li><a href="https://quarkusio.zulipchat.com">Chatroom</a></li>
          
        </ul>
      </div>
    

    
      <div class="width-3-12 more-links">
        <span>Quarkus is made of community projects</span>
        <ul class="footer-links">
          
            <li><a href="https://vertx.io/" target="_blank">Eclipse Vert.x</a></li>
          
            <li><a href="https://microprofile.io" target="_blank">Eclipse MicroProfile</a></li>
          
            <li><a href="https://hibernate.org" target="_blank">Hibernate</a></li>
          
            <li><a href="https://netty.io" target="_blank">Netty</a></li>
          
            <li><a href="https://resteasy.github.io" target="_blank">RESTEasy</a></li>
          
            <li><a href="https://camel.apache.org" target="_blank">Apache Camel</a></li>
          
            <li><a href="https://code.quarkus.io/" target="_blank">And many more...</a></li>
          
        </ul>
      </div>
    
  </div>
</div>
  <div class="content redhat-footer">
  <div class="grid-wrapper">
    <span class="licence">
      <i class="fab fa-creative-commons"></i><i class="fab fa-creative-commons-by"></i> <a href="https://creativecommons.org/licenses/by/3.0/" target="_blank">CC by 3.0</a> | <a href="https://www.redhat.com/en/about/privacy-policy">Privacy Policy</a>
    </span>
    <span class="redhat">
      Sponsored by
    </span>
    <span class="redhat-logo">
      <a href="https://www.redhat.com/" target="_blank"><img src="/assets/images/redhat_reversed.svg"></a>
    </span>
  </div>
</div>


  <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js" integrity="sha384-8gBf6Y4YYq7Jx97PIqmTwLPin4hxIzQw5aDmUg/DDhul9fFpbbLcLh3nTIIDJKhx" crossorigin="anonymous"></script>
  <script type="text/javascript" src="/assets/javascript/mobile-nav.js"></script>
  <script type="text/javascript" src="/assets/javascript/scroll-down.js"></script>
  <script src="/assets/javascript/satellite.js" type="text/javascript"></script>
  <script src="https://quarkus.io/guides/javascript/config.js" type="text/javascript"></script>
  <script src="/assets/javascript/search-filter.js" type="text/javascript"></script>
  <script src="/assets/javascript/back-to-top.js" type="text/javascript"></script>
</body>

</html>
